﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using System.Linq;
using System.Net;
using GMap.NET;
using GMap.NET.MapProviders;
using GMap.NET.WindowsForms;
using GMap.NET.WindowsForms.Markers;
using TaxiDispatchClient.Properties;
using Model;
using Common;
using TaxiDispatchClient.Service;

namespace TaxiDispatchClient
{
    public partial class AdMachineMainForm : DevExpress.XtraEditors.XtraForm
    {
        public AdMachineMainForm()
        {
            InitializeComponent();
            Init();
        }
        
        private GMapOverlay _overlay;
        private PointLatLng _currentLatLng;
        private Hashtable _stationList = Hashtable.Synchronized(new Hashtable());
        private GMapMarker _currentMarker;
        private bool _isLoadOver;
        private UdpServer _udpServer;
        private IPEndPoint _serviceIpEnd;
        private bool _isListen;
        private DataTable _dtStations;
        private bool _hasGridBind;
        private Thread _threadGetOnlineStations;
        private double _newestVersion;
        private void Init()
        {
            DevExpress.Data.CurrencyDataController.DisableThreadingProblemsDetection = true;
            
            //Map
            double theCenterLat = Settings.Default.MainMapLat;
            double theCenterLng = Settings.Default.MainMapLng;
            MainMap.Manager.Mode = AccessMode.ServerAndCache;
            MainMap.MapProvider = GMapProviders.GoogleChinaMap;           
            _overlay = new GMapOverlay("Overlay");
            MainMap.Overlays.Add(_overlay);
          
            MainMap.MaxZoom = 18;
            MainMap.MinZoom = 10;

            MainMap.Zoom = 12;
            MainMap.Position = new PointLatLng(theCenterLat, theCenterLng);
            MainMap.DragButton = MouseButtons.Left;

            // trackBarControl_MapZoom
            trackBarControl_MapZoom.Properties.Minimum = MainMap.MinZoom;
            trackBarControl_MapZoom.Properties.Maximum = MainMap.MaxZoom;
            trackBarControl_MapZoom.Value = (int)MainMap.Zoom;

            //_dtStations
            _dtStations = new DataTable();
            DataColumn[] keycolumn = new DataColumn[1];
            DataColumn keycol = new DataColumn("id", typeof(string));
            keycolumn[0] = keycol;
            _dtStations.Columns.Add(keycol);
            _dtStations.PrimaryKey = keycolumn;
            
            _dtStations.Columns.Add("Number");
            _dtStations.Columns.Add("StationName");
            _dtStations.Columns.Add("State");
            _dtStations.Columns.Add("Version");
            _dtStations.Columns.Add("Lat");
            _dtStations.Columns.Add("Lng");

            _isListen = true;


            Thread getNewestVersion = new Thread(GetNewestVersion);
            getNewestVersion.IsBackground = true;
            getNewestVersion.Start();

            Thread getStations = new Thread(GetStationsFromDatabase);
            getStations.IsBackground = true;
            getStations.Start();

            Thread updateStationsOnMap =new Thread(UpdateStationsOnMap);
            updateStationsOnMap.IsBackground = true;
            updateStationsOnMap.Start();

            _udpServer = new UdpServer(ConstParameters.PlatformStationPort);
            _udpServer.OnReceivedData += server_OnDataReceived;
            _udpServer.Start();

            Thread getServerEndpoint = new Thread(GetServerIp);
            getServerEndpoint.IsBackground = true;
            getServerEndpoint.Start();

            _threadGetOnlineStations = new Thread(SendDataGetStationList);
            _threadGetOnlineStations.IsBackground = true;
            _threadGetOnlineStations.Start();
        }
        
        private void GetNewestVersion()
        {
            byte[] data = OperateAgreement.GetEmptyBodyMessageData(
              ConstParameters.CmdStationGetClientVersion);
            while (true)
            {
                if (_serviceIpEnd == null)
                {
                    Thread.Sleep(500);
                    continue;
                }
                _udpServer.SendData(data, _serviceIpEnd);
                Thread.Sleep(60*60*1000);
            }
        }

        private void GetStationsFromDatabase()
        {
            while (_isListen)
            {
                #region  每二十秒钟从数据库中获取一次广告机信息
                DataSet ds = MainForm.PositionService.AdMachineGetList("");
                if (ds == null || ds.Tables.Count==0 
                    ||ds.Tables[0].Rows.Count == 0)
                {
                    Thread.Sleep(2000);
                    continue;
                }
                DataTable dt = _dtStations.Clone();
                //从数据库中获取所有广告机信息 更新_stationList
                foreach (DataRow row in ds.Tables[0].Rows)
                {
                    ADMachineInfo model = new ADMachineInfo();
                    model.id = int.Parse(row["id"].ToString());
                    model.Address = row["Address"].ToString();
                    model.ExitPassword = row["ExitPassword"].ToString();
                    model.ImageUrl = row["ImageUrl"].ToString();
                    model.InternetType = row["InternetType"].ToString();
                    model.Latitude = double.Parse(row["Latitude"].ToString());
                    model.Longitude = double.Parse(row["Longitude"].ToString());
                    model.Linkman = row["Linkman"].ToString();
                    model.Number = row["Number"].ToString();
                    model.PhoneNumber = row["PhoneNumber"].ToString();
                    model.StationName = row["StationName"].ToString();
                    model.Telephone = row["Telephone"].ToString();
                    model.XTRemoteId = row["XTRemoteID"].ToString();

                    if (!_stationList.Contains(model.Number))
                    {
                        AdStation station = new AdStation();
                        station.Machine = model;
                        _stationList.Add(model.Number,station);
                    }
                    else
                    {
                        AdStation station =
                        _stationList[model.Number] as AdStation;
                        station.Machine = model;
                    }

                   
                    DataRow dr = dt.Rows.Find(model.id);
                    if (dr == null)
                    {
                        dr = dt.NewRow();
                        dr["id"] = model.id;
                        dr["Number"] = model.Number;
                        dr["StationName"] = model.StationName;                        
                        dr["Lat"] = model.Latitude;
                        dr["Lng"] = model.Longitude;
                        dr["State"] = "未知";
                        dr["Version"] = "未知";
                        dt.Rows.Add(dr);
                    }
                    else
                    {
                        dr["id"] = model.id;
                        dr["Number"] = model.Number;
                        dr["StationName"] = model.StationName;
                        dr["Lat"] = model.Latitude;
                        dr["Lng"] = model.Longitude;                        
                    }                   
                }
                _dtStations = dt;
                if (!_hasGridBind)
                {
                    BeginInvoke(new MethodInvoker(() => gridControl1.DataSource = _dtStations));
                    _hasGridBind = true;
                }
                //删除_stationList中在数据库里无记录的项
                List<string> delKeys = new List<string>();
                lock (_stationList.SyncRoot)
                {
                    foreach (AdStation station in _stationList.Values)
                    {
                        DataRow[] rows = ds.Tables[0].Select("Number='"
                            + station.Machine.Number + "'");
                        if (rows.Length == 0)
                        {
                            delKeys.Add(station.Machine.Number);
                        }
                    }
                    foreach (string number in delKeys)
                    {
                        _stationList.Remove(number);
                    }
                }
                _isLoadOver = true;
                Thread.Sleep(20000);
                #endregion
            }           
        }

        private void UpdateStationsOnMap()
        {
            while (_isListen)
            {
                #region  每八秒钟在地图上刷新一次各站点信息

                lock (_stationList.SyncRoot)
                {
                    lock (_overlay.Markers)
                    {
                        try
                        {
                            //更新地图上各个站点的状态
                            foreach (AdStation station in _stationList.Values)
                            {
                                GMapMarker g = _overlay.Markers.FirstOrDefault(
                                    marker => marker.Tag != null &&
                                        marker.Tag.ToString() ==
                                    station.Machine.Number);
                                if (g != null)
                                {
                                    BeginInvoke(new MethodInvoker(() =>
                                        _overlay.Markers.Remove(g)));
                                }

                                PointLatLng point = new PointLatLng(
                                 station.Machine.Latitude, station.Machine.Longitude);
                                Bitmap obj = TaxiState._364;
                                string tooltiptxt;
                                if (station.IsOnline)
                                {
                                    if (station.Version == 0)
                                    {
                                        obj = Resources.adMachine_yellow_40; //联网但未版本号未知
                                        tooltiptxt = "已连接服务器，但版本号未知！";
                                    }
                                    else
                                    {
                                        obj = Resources.adMachine_green_40;//联网且已知版本号(正常)
                                        tooltiptxt = "正常";
                                    }
                                }
                                else
                                {
                                    if (station.Version==0)
                                    {
                                        obj = Resources.adMachine_red_40;//未联网
                                        tooltiptxt = "长时间未连接服务器！";    
                                    }
                                    else
                                    {
                                        obj = Resources.adMachine_gray_40;//未联网
                                        tooltiptxt = "连接服务器后断开！";    
                                    }
                                }
                                AdMachineMarker gmarker = new AdMachineMarker(point, obj,station.Machine.StationName)
                                {
                                    Tag = station.Machine.Number,                                    
                                    ToolTipText = "站点名称： "+station.Machine.StationName+
                                    Environment.NewLine+"站点编号： "+
                                    station.Machine.Number+
                                    Environment.NewLine+"程序版本号： "+
                                    station.Version+
                                    Environment.NewLine+"状态： "+
                                    tooltiptxt,
                                    ToolTipMode = MarkerTooltipMode.OnMouseOver                                    
                                };
                                gmarker.ToolTip.Format.Alignment = StringAlignment.Near;
                                BeginInvoke(new MethodInvoker(() =>
                                        _overlay.Markers.Add(gmarker)));
                            }
                            //删除地图上多余的站点（数据库中已删除，但地图上仍存在的）
                            foreach (GMapMarker marker in _overlay.Markers)
                            {
                                if (!_stationList.Contains(marker.Tag.ToString()))
                                {
                                    BeginInvoke(new MethodInvoker(() =>
                                            _overlay.Markers.Remove(marker)));    
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                          
                        }                    
                    }                   
                }
                if (_isLoadOver)
                {
                    Thread.Sleep(8000);
                }                    
                else
                {
                    Thread.Sleep(1500);
                }
                #endregion
            }
        }


        private void server_OnDataReceived(object sender, EventArgs e)
        {
            SocketAsyncEventArgs socketAsyncEventArgs = e as SocketAsyncEventArgs;
            if (socketAsyncEventArgs != null)
            {
                List<string> onlineList = new List<string>();
                if (socketAsyncEventArgs.BytesTransferred >= ConstParameters.MhLenth)
                {
                    byte[] receData = new byte[socketAsyncEventArgs.BytesTransferred];
                    Array.Copy(socketAsyncEventArgs.Buffer, 0, receData, 0, receData.Length);                   
                    if (receData.Length > ConstParameters.MhLenth)
                    {
                        ushort cmdId = OperateAgreement.GetMessageIdInMessageHead(receData);
                        try
                        {
                            if (cmdId == ConstParameters.CmdGetStationListReply)
                            {
                                int count = receData.Length - 19;
                                count = count / 10;
                                lock (_stationList.SyncRoot)
                                {
                                    for (int i = 0; i < count; i++)
                                    {

                                        byte[] bytesnumber = new byte[6];
                                        Array.Copy(receData, ConstParameters.MBodySatrtIndex + i * 10, bytesnumber, 0, 6);
                                        string number = CommonRoutine.ByteToBcdString(bytesnumber);
                                        onlineList.Add(number);
                                        float version = BitConverter.ToSingle(receData, ConstParameters.MBodySatrtIndex + 6 + i * 10);

                                        number = number.Remove(0, 1);
                                        AdStation station = _stationList[number]
                                                            as AdStation;
                                        if (station != null)
                                        {
                                            station.IsOnline = true;
                                            station.Version = version;
                                        }
                                        DataRow[] row = _dtStations.Select("Number='" + number + "'");
                                        if (row.Length > 0)
                                        {
                                            row[0]["State"] = "在线";
                                            row[0]["Version"] = version;
                                        }
                                    }
                                }

                                lock (_stationList.SyncRoot)
                                {
                                    foreach (AdStation station in _stationList.Values)
                                    {
                                        if (!onlineList.Select(s => s.Remove(0, 1) == station.Machine.Number).Any())
                                        {
                                            station.IsOnline = false;
                                        }
                                    }
                                }
                                foreach (DataRow row in _dtStations.Rows)
                                {
                                    string strPhone = "1"+row["Number"].ToString();
                                    if (!onlineList.Contains(strPhone))
                                    {
                                        row["State"] = "离线";
                                    }

                                    //onlineList.Select(s => s.Remove(0, 1) == row["Number"]);
                                    //if (!onlineList.Select(s => s.Remove(0, 1) == row["Number"]).Any())
                                    //{
                                    //    row["State"] = "离线";
                                    //}
                                }
                            }
                            else if (cmdId == ConstParameters.CmdStationClientVersionReply)
                            {
                                double version = BitConverter.ToDouble(receData,
                                      ConstParameters.MBodySatrtIndex);
                                BeginInvoke(new MethodInvoker(() =>
                                    {
                                        barStaticItem_newestVersion.Caption = "程序最新版本号：" + version;
                                        _newestVersion = version;
                                    }                                    
                                    ));
                            }
                        }
                        catch (Exception ex)
                        {
                            CommonRoutine.HandlingExceptions(ex);
                            Console.WriteLine(ex.Message);
                        }
                        
                    }
                }
                //在线的站点
                //foreach (string s in onlineList)
                //{
                //    string number = s.Remove(0, 1);
                //    AdStation station = _stationList[number]
                //        as AdStation;
                //    if (station != null)
                //    {
                //        station.IsOnline = true;
                //    }                
                //}
                //不在线的站点
               

            }
        }

        private void SendDataGetStationList()
        {
            byte[] data = OperateAgreement.GetEmptyBodyMessageData(
                       ConstParameters.CmdGetStationList);
            while (true)
            {               
                if (_serviceIpEnd==null)
                {
                    Thread.Sleep(500);
                    continue;
                }
                _udpServer.SendData(data,_serviceIpEnd);
                Thread.Sleep(10000);
            }
        }

        private void GetServerIp()
        {            
            while (_isListen)
            {
                string positionIp = Settings.Default.PositionServerIP;
                try
                {                  
                    IPAddress[] ips = Dns.GetHostAddresses((string)positionIp);
                    IPAddress ip = ips.Length > 0 ? ips[0] : IPAddress.Parse("219.140.165.6");
                    LogService.WriteDebugLog("解析的" + positionIp + "IP:为" + ip.ToString(), DateTime.Now);
                    if (ips.Length == 0)
                    {
                        Thread.Sleep(2000);
                        LogService.WriteLog(positionIp + "解析域名失败...");
                    }
                    else
                    {
                        _serviceIpEnd = new IPEndPoint(ip, ConstParameters.AstPort);
                        break;
                    }
                }
                catch (Exception ex)
                {
                    Thread.Sleep(2000);
                    LogService.WriteLog(positionIp + "解析域名失败...");
                }
            }
        }

        private void MainMap_MouseClick(object sender, MouseEventArgs e)
        {
            
            if (e.Button == MouseButtons.Right)
            {

                RectLatLng selRect = MainMap.SelectedArea;
                if (selRect.Bottom != 0 && selRect.Top != 0
                    && selRect.WidthLng != 0 && selRect.HeightLat != 0)
                {
                    barBtn_setSelectedAd.Enabled = true;
                    barBtn_addMachine.Enabled = false;
                }
                else
                {
                    _currentLatLng = MainMap.FromLocalToLatLng(
                        e.X, e.Y);
                    barBtn_setSelectedAd.Enabled = false;
                    barBtn_addMachine.Enabled = true;
                }
                
                popupMenu_MouseRight.ShowPopup(Cursor.Position);    
            }
             
        }

        private void barBtn_addMachine_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {            
            AdMachineAddForm adMachineAdd = 
            new AdMachineAddForm(_currentLatLng.Lat,_currentLatLng.Lng);
            adMachineAdd.ShowDialog();
        }
         
        private void trackBarControl_MapZoom_Properties_ValueChanged(object sender, EventArgs e)
        {
            MainMap.Zoom = (trackBarControl_MapZoom.Value);
        }

        private void MainMap_OnMapZoomChanged()
        {
            trackBarControl_MapZoom.Value = (int)(MainMap.Zoom);
        }
          
        private void MainMap_OnMarkerClick(GMapMarker item, MouseEventArgs e)
        {
            _currentMarker = item;
           popupMenu_MouseLeft.ShowPopup(Cursor.Position);           
        }

        private void barBtn_deleteStation_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (XtraMessageBox.Show("是否确定删除该终端站点？", "警告：",
                                    MessageBoxButtons.YesNo) == DialogResult.No)
            {
                return;
            }
            if (_currentMarker==null)
            {
                XtraMessageBox.Show("请先选择想要删除的站点！");
                return;
            }

            string number = _currentMarker.Tag.ToString();
            if (MainForm.PositionService.AdMachineDelete(
                number))
            {
                XtraMessageBox.Show("删除成功！");
                _stationList.Remove(number);
                _overlay.Markers.Remove(_currentMarker);
                DataRow[] row = _dtStations.Select("Number='"+number+"'");
                if (row.Length>0)
                {
                    _dtStations.Rows.Remove(row[0]);    
                }                
                RefreshGridView();
            }
            else
            {
                XtraMessageBox.Show("删除失败！"); 
            }
        }

        private void barBtn_stationInfo_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            AdStation station = _stationList[_currentMarker.Tag.ToString()] as AdStation;
            if (station!=null)
            {
               AdMachineAddForm adMachineAdd = new AdMachineAddForm(station.Machine);
                adMachineAdd.ShowDialog();
            }
            else
            {
                XtraMessageBox.Show("未找到该站点，请稍后查看！");
            }
        }


        public class AdStation
        {
            public ADMachineInfo Machine;
            public bool IsOnline;
            public float Version;
            public AdStation()
            {
                Machine = new ADMachineInfo();
                IsOnline = false;
                Version = 0;
            }
        }

        private void AdMachineMainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_threadGetOnlineStations != null)
            {
                _threadGetOnlineStations.Abort();
            }
            _isListen = false;           
            _udpServer.Stop();           
        }

        private void barBtn_setSelectedAd_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            RectLatLng selRect = MainMap.SelectedArea;
            List<string> selectedStations = new List<string>();
            lock (_stationList.SyncRoot)
            {
                foreach (AdStation station in _stationList.Values)
                {
                    double lat = station.Machine.Latitude;
                    double lng = station.Machine.Longitude;
                    if (lng > selRect.Left && lng < selRect.Right
                        && lat > selRect.Bottom && lat < selRect.Top)
                    {
                        selectedStations.Add(station.Machine.Number);
                    }
                }               
            }
             
            string notice = "您共选择了以下站点：" + Environment.NewLine;
            foreach (string numb in selectedStations)
            {
                notice += numb + Environment.NewLine;
            }
            notice += "共计" + selectedStations.Count + "个";
            notice += Environment.NewLine + "是否统一配置广告？";
            bool flag = XtraMessageBox.Show(notice, "提醒：",
                MessageBoxButtons.YesNo)
                        == DialogResult.Yes;
            if (flag)
            {
                AdMachineAdListForm adListForm =
                    new AdMachineAdListForm(selectedStations);
                adListForm.ShowDialog();
            }

        }

        private void gridView1_MouseUp(object sender, MouseEventArgs e)
        {
            DataRow row = gridView1.GetDataRow(gridView1.FocusedRowHandle);
            if (row==null)
            {
                return;
            }

            string number = row["Number"].ToString();

            GMapMarker g = _overlay.Markers.FirstOrDefault(
                            marker => marker.Tag != null &&
                                marker.Tag.ToString() == number);
            if (g != null)
            {
                _currentMarker = g;
            }

            if (e.Button==MouseButtons.Left)
            {
                double lat = double.Parse(row["Lat"].ToString());
                double lng = double.Parse(row["Lng"].ToString());               
                MainMap.Position = new PointLatLng(lat, lng);
            }
            else
            {
                popupMenu_MouseLeft.ShowPopup(Cursor.Position);
            }
        }
        private void barBtnItem_ListModel_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (!panel_list.Visible)
            {
                panel_list.Visible = true;
                barBtnItem_ListModel.Glyph = Resources.btn_hideList_100;
                RefreshGridView();
            }
            else
            {
                panel_list.Visible = false;
                barBtnItem_ListModel.Glyph = Resources.btn_showList_100;
            }
        }

        private void btn_refreshGrid_Click(object sender, EventArgs e)
        {
            RefreshGridView();
        }

        private void RefreshGridView()
        {
            btn_refreshGrid.Enabled = false;
            gridControl1.DataSource = _dtStations;
            int updatedcount = 0;
            int onlinecount = 0;
            lock (_stationList.SyncRoot)
            {
                foreach (AdStation station in _stationList.Values)
                {
                    if (station.IsOnline)
                    {
                        onlinecount++;
                    }
                    if (Math.Abs(station.Version - _newestVersion) < 0.01)
                    {
                        updatedcount++;
                    }
                }
            }
            if (_newestVersion < 1)
            {
                label_updatedCount.Text = "未知";
            }
            else
            {
                label_updatedCount.Text = updatedcount.ToString();
            }
            label_stationCount.Text = _stationList.Count.ToString();
            label_onlineCount.Text = onlinecount.ToString();
            btn_refreshGrid.Enabled = true;
        }

        private void barBtnItem_AddFromExcel_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            AdMachineAddFromExcelForm form = new AdMachineAddFromExcelForm();
            form.ShowDialog();
        }

        private void barBtnItem_listForm_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            AdMachineListForm listForm = new AdMachineListForm();
            listForm.ShowDialog();
        }

      

        
    }
}